package rothag.models;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Classe de sérialisation des parties
 * @author Gaetan
 */
public class Serialisation extends ModelBase {

    public static String path;
    private static Serialisation singleton;
    private ArrayList<Partie> topTen;
    private Map<UUID, Partie> sauvegardes;

    /**
     * Constructeur static
     */
    static {
        try {
            // Récupération du chemin du fichier de sauvegarde
            path = new File(".").getCanonicalPath() + "/savegame.rothag";
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }

    /**
     * Constructeur
     */
    private Serialisation() {
        topTen = new ArrayList<Partie>();
        sauvegardes = new HashMap<UUID, Partie>();
    }

    /**
     * Désérialisation du fichier de sauvegarde
     * @throws Exception Fichier de sauvegarde invalide
     */
    public static void deserialiserSingleton() throws Exception {
        FileInputStream fichier = null;
        try {
            fichier = new FileInputStream(path);
            ObjectInputStream ois = new ObjectInputStream(fichier);
            Object o = ois.readObject();
            singleton = (Serialisation) o;
            if (singleton == null) {
                singleton = new Serialisation();
            }
            fichier.close();
        } catch (FileNotFoundException ex) {
            singleton = new Serialisation();
        }
    }

    /**
     * Sérialise le singleton dans le fichier de sauvegarde
     */
    private static void serialiserSingleton() {
        FileOutputStream fichier = null;

        try {
            fichier = new FileOutputStream(path);
            ObjectOutputStream oos = new ObjectOutputStream(fichier);
            oos.writeObject(singleton);
            oos.flush();
            oos.close();
            fichier.close();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }

    /**
     * Retourne le singleton permettant la gestion des sauvegardes
     * @return
     */
    private static Serialisation getSingleton() {
        return singleton;
    }

    /**
     * Ajoute une partie au top 10
     * @param Partie Partie à ajouter
     * @return Renvoie -1 si la partie n'est pas dans le top 10, sinon renvoie la position dans le top 10
     * @throws Exception Fichier de sauvegarde invalide
     */
    public static int ajouterScore(Partie partie) throws Exception {
        int retour = -1;

        // Lecture du fichier
        deserialiserSingleton();

        // Partie solo uniquement, on prend le premier joueur
        int score = partie.getListeJoueur().get(0).getScore();

        ArrayList<Partie> listeTopTen = singleton.topTen;

        for (int i = 0; i < listeTopTen.size(); i++) {
            if (listeTopTen.get(i).getListeJoueur().get(0).getScore() < score) {
                // Score meilleur de le iéme, on insère la partie avant
                singleton.topTen.add(i, partie);
                // Calcul du classement
                retour = i + 1;
                break;
            }
        }

        if (retour == -1 && listeTopTen.size() < 10) {
            // Il n'y a pas 10 parties dans la liste et le joueur n'a pas été classé
            // On insère donc la partie à la fin
            singleton.topTen.add(partie);
            retour = singleton.topTen.size();
        }

        if (listeTopTen.size() > 10) {
            // Suppression du dernier élèment
            singleton.topTen.remove(listeTopTen.size() - 1);
        }

        try {
            // Sauvegarde du singleton
            serialiserSingleton();
        } catch (Exception ex) {
            Logger.getLogger(Serialisation.class.getName()).log(Level.SEVERE, null, ex);
        }

        return retour;
    }

    /**
     * Sauvegarde la partie dans le fichier de sauvegarde
     * @param partie Partie à sauvegarder
     * @throws Exception Fichier de qauvegarde invalide
     */
    public static void sauvegarderPartie(Partie partie) throws Exception {
        deserialiserSingleton();

        partie.setDerniereSauvegarde(new Date());

        if (singleton.sauvegardes.containsKey(partie.getIdentifiant())) {
            // Si la partie existe déjà on la supprime du dictionnaire
            singleton.sauvegardes.remove(partie.getIdentifiant());
        }

        // Ajout de la partie dans le dictionnaire
        singleton.sauvegardes.put(partie.getIdentifiant(), partie);

        // Sérialisation
        serialiserSingleton();
    }

    /**
     * Retourne la liste des parties sauvegardés
     * @return Dictionnaire de parties
     * @throws Exception Fichier de sauvegarde non valide
     */
    public static Map<UUID, Partie> getSauvegardes() throws Exception {
        deserialiserSingleton();
        return getSingleton().sauvegardes;
    }

    /**
     * Retourne le top 10
     * @return Une liste de parties
     * @throws Exception Fichier de sauvegarde invalide
     */
    public static ArrayList<Partie> getTopTen() throws Exception {
        deserialiserSingleton();
        return getSingleton().topTen;
    }
}
